<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>nginx反向代理</title>
    <style>
        button{
            background: #74afff;
            border:0;
            outline: 0;
            color:#fff;
            padding:6px 12px;
            border-radius:3px;
            cursor: pointer;
        }
        button:hover{
            background: #6396da;
        }
    </style>
</head>
<body>
<div style="margin-bottom:50px;">
    <h2>nginx反向代理:</h2>
    <p>  服务器向服务器请求无需遵循同源策略,所以可以搭建一个中转nginx服务器，用于转发请求。
    </p>
    <p>使用nginx反向代理实现跨域，是最简单的跨域方式。只需要修改nginx的配置即可解决跨域问题，支持所有浏览器，支持session，不需要修改任何代码，并且不会影响服务器性能。</p>
    <p>实现思路：通过nginx配置一个代理服务器（域名与domain1相同，端口不同）做跳板机，反向代理访问domain2接口，并且可以顺便修改cookie中domain信息，方便当前域cookie写入，实现跨域登录。</p>
    <p>下载nginx，然后将nginx目录下的nginx.conf修改如下:</p>
    <pre style="padding:20px;">

// proxy服务器
server {
    listen       81;
    server_name  www.domain1.com;
    location / {
        proxy_pass   http://www.domain2.com:8080;  #反向代理
        proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名
        index  index.html index.htm;

        # 当用webpack-dev-server等中间件代理接口访问nignx时，此时无浏览器参与，故没有同源限制，下面的跨域配置可不启用
        add_header Access-Control-Allow-Origin http://www.domain1.com;  #当前端只跨域不带cookie时，可为*
        add_header Access-Control-Allow-Credentials true;
    }
}

    </pre>
</div>
<button onclick="get()">get请求</button>
<br><br>

<form action="/post">
    <input type="text" name="name">
    <button onclick="post()" type="submit">post请求</button>
</form>
<div id="result" style="color:#f00;padding:20px;"></div>
</body>
<script>
    function ajax(options){
        return new Promise((resolve,reject)=>{
            // 请求地址
            let url = options.url?options.url:''
            // 请求方法
            let method = options.method ? options.method : 'GET'
            method = method.toUpperCase()
            // 默认为异步true
            let async = options.async?options.async:true
            // 请求发送参数
            let data =  queryUrlParams(options.data)
            //设置头信息
            let reqHeader = options.setRequestHeader?options.setRequestHeader:{}

            //响应服务器的数据类型
            let responseType = options.responseType?options.responseType : 'responseText'
            //等待响应的时间
            let timeout = options.timeout?options.timeout:2000
            //实例化ajax对象 IE7+ Firefox, Chrome, Opera, Safari 浏览器执行代码
            let xhr = new XMLHttpRequest()

            //提取发送数据方法
            function queryUrlParams(urlParams){
                //判断是否是对象类型
                // if(Object.prototype.toString.call(urlParams) !== '[object Object]'){
                //     throw new TypeError('data must be of object type')
                // }
                let result = ''
                for(let key in urlParams){
                    if(urlParams.hasOwnProperty(key)){
                        result +=key + '=' + urlParams[key] + '&'
                    }
                }
                return result.slice(0,result.length-1)
            }

            //设置RequestHeader方法
            function setRequestHeader(_xhr,_reqHeader){
                for(let [key,value] of Object.entries(_reqHeader)){
                    _xhr.setRequestHeader(key,value)
                }
            }

            //处理GET请求方式的请求发送参数
            if(method === 'GET'){
                //检测url中是否有?
                const index = url.indexOf('?')
                if(data.length>0){
                    if(index === -1){
                        url += '?'
                    }else{
                        url += '&'
                    }
                }
                //拼接url
                url += data
                xhr.open(method,url,async)
                xhr.send(null)
            }else if(method === 'POST'){
                xhr.open(method,url,async)
                setRequestHeader(xhr,reqHeader)
                xhr.send(data)
            }else{
                reject('TypeError method')
            }

            xhr.onreadystatechange = function(){
                let timer = null
                if( xhr.readyState === 4 && xhr.status === 200){
                    if(responseType === 'responseText'){
                        clearTimeout(timer)
                        resolve(xhr.responseText)
                    }else if(responseType === 'responseXML'){
                        resolve(xhr.responseText)
                    }
                    else{
                        reject('RangeError:responseType is not allowed to be '+responseType)
                    }
                }
                timer = setTimeout(()=>{
                    clearTimeout(timer)
                    reject('status:'+xhr.status)
                },timeout)
            }
        })
    }
</script>
<script>
    let text = document.getElementById('result')
    let url = 'http://localhost:8080/get'
    //测试get请求
    async function get(){
        try{
            let result =await ajax({
                url:url,
                method:'get'
            })
            console.log(result)
            text.innerHTML = 'result:'+ result
        }catch (error){
            console.log(error)
        }
    }


    //测试get请求
    async function post(){
        try{
            let result =await ajax({
                url:'http://localhost:8080/post',
                method:'post',
                data:{
                    name:'hli',
                    id:'2020'
                },
                //注意：这里要设置requestheader,那么在服务端必须要允许
                // 'Access-Control-Allow-Headers': 'Content-Type,Token'
                setRequestHeader:{
                    'Content-Type':'application/x-www-form-urlencoded;charset=UTF-8',
                    'Token':'get token....................................',
                }
            })
            console.log(result)
            text.innerHTML = 'result:'+ result
        }catch (error){
            console.log(error)
        }
    }
</script>
</html>